﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using JigLibX.Geometry;
using JigLibX.Physics;
using JigLibX.Math;
using JigLibX.Collision;


namespace RPG
{
    public struct EntityData
    {
        public float MoveSpeed;
        public float TurnSpeed;
        public float MaxHealthPoints;
        public float CurrentHealthPoints;
    }

    public class CGameEntity : CGameObject
    {

        public CGameEntity(Vector3 _position, float _mass, Vector3 _scale)
        {
            m_Body = new Body();
            
            m_Scale = _scale;

            m_CollisionSkin = new CollisionSkin(m_Body);
            m_CollisionSkin.AddPrimitive(new Box(Vector3.Zero, Matrix.Identity, _scale), (int)MaterialTable.MaterialID.NormalNormal);
            m_Body.CollisionSkin = m_CollisionSkin;

            m_CenterOfMass = SetMass(_mass);

            Position = _position;

            m_Rotation = Quaternion.CreateFromRotationMatrix(Body.Orientation);

            m_EntityData.MoveSpeed = 120f;
            m_EntityData.TurnSpeed = 80f;
            m_EntityData.MaxHealthPoints = 100;
            m_EntityData.CurrentHealthPoints = 100;

            m_Body.EnableBody();
        }

        public Vector3 SetMass(float _mass)
        {
            PrimitiveProperties primProps = new PrimitiveProperties(
            PrimitiveProperties.MassDistributionEnum.Solid,
            PrimitiveProperties.MassTypeEnum.Mass,
            _mass);

            float junk;
            Matrix it;
            Matrix itCoM;
            Vector3 com;

            m_CollisionSkin.GetMassProperties(primProps, out junk, out com, out it, out itCoM);

            m_Body.BodyInertia = itCoM;
            m_Body.Mass = junk;

            return com;
        }

        public override void Update(GameTime gameTime)
        {
            
        }

        public override void Draw(GameTime gameTime, CGameCamera camera)
        {
            if (Model == null)
                return;
            Matrix[] transforms = new Matrix[m_Model.Bones.Count];
            m_Model.CopyAbsoluteBoneTransformsTo(transforms);

            foreach (ModelMesh mesh in m_Model.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.EnableDefaultLighting();
                    effect.PreferPerPixelLighting = true;
                    effect.World = transforms[mesh.ParentBone.Index] * GetWorldMatrix();
                    effect.View = camera.ViewMatrix;
                    effect.Projection = camera.ProjectionMatrix;
                }
                mesh.Draw();
            }
        }


        //Non-public
        protected Vector3 m_Scale;
        protected Model m_Model;

        protected Body m_Body;
        protected CollisionSkin m_CollisionSkin;

        protected Vector3 m_CenterOfMass;

        protected EntityData m_EntityData;

        //Accessors
        public Model Model
        {
            get
            {
                return m_Model;
            }
            set
            {
                m_Model = value;
            }
        }

        private Matrix GetWorldMatrix()
        {
            return
                    Matrix.CreateScale(m_Scale) *
                    m_CollisionSkin.GetPrimitiveLocal(0).Transform.Orientation *
                    m_Body.Orientation *
                    Matrix.CreateTranslation(Position);
        }

        public EntityData EntityData
        {
            get
            {
                return m_EntityData;
            }
            set
            {
                m_EntityData = value;
            }
        }

        public Body Body
        {
            get
            {
                return m_Body;
            }
            set
            {
                m_Body = value;
            }
        }

        public CollisionSkin CollisionSkin
        {
            get
            {
                return m_CollisionSkin;
            }
            set
            {
                m_CollisionSkin = value;
            }
        }

        public override Quaternion Rotation
        {
            get
            {
                return Quaternion.CreateFromRotationMatrix(Body.Orientation);
            }
            set
            {
                Body.MoveTo(Body.Position, 
                    Matrix.CreateFromQuaternion(value));
                m_Rotation = value;
            }
        }

        public override Vector3 Position
        {
            get
            {
                return m_Body.Position;
            }
            set
            {
                m_Body.MoveTo(value, Matrix.Identity);
                m_CollisionSkin.ApplyLocalTransform(new Transform(-m_CenterOfMass, Matrix.Identity));
            }
        }
    }
}
